<?php
declare(strict_types=1);

namespace App\Utils;

use Hyperf\Logger\Logger;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Redis\Redis;
use Hyperf\Utils\Context;

/**
 * @Description 后端一些工具方法类
 * @author wuxian
 * @since 2020-04-15
 */
class ServerUtil
{
    /**
     * @return string
     * @Description  生成订单号
     * @author wuxian
     * @since 2020-04-16
     */
    public static function orderNo(): string
    {
        list($msec, $sec) = explode(' ', microtime());
		$msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
		return date('YmdHis').$msectime;
    }

    /**
     * @param [type] $mobile  要查询的号码
     * @return array
     * @Description 通过号码查询相关信息
     * @author wuxian
     * @since 2020-04-16
     */
    public static function getMobileInfo($mobile)
    {
        $phone_json = file_get_contents('http://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query={'.$mobile.'}&resource_id=6004&ie=utf8&oe=utf8&format=json');
        $phone_array = json_decode($phone_json,true);
        $info = [];
        $info['phone'] = $mobile;
        if($phone_array['status'] == 0 && $phone_array['data']){
            if(empty($phone_array['data'][0]['prov'])){
                $info['phoneArea'] = $phone_array['data'][0]['city'].'市';
            }else{
                $info['phoneArea'] = $phone_array['data'][0]['prov'].'省';
            }
            if(stripos($phone_array['data'][0]['type'], '联通') !== false){
                $info['phoneType'] = 3;
            }else if(stripos($phone_array['data'][0]['type'],'移动') !== false){
                $info['phoneType'] = 1;
            }else if(stripos($phone_array['data'][0]['type'], '电信') !== false){
                $info['phoneType'] = 2;
            }else{
                $info['phoneType'] = 0;
            }
            
        }else{
            $info['phoneType'] = 0;
        }
        return $info;
        
    }

    /*
     * 经典的概率算法，
     * $proArr是一个预先设置的数组，
     * 假设数组为：array(100,200,300，400)，
     * 开始是从1,1000 这个概率范围内筛选第一个数是否在他的出现概率范围之内， 
     * 如果不在，则将概率空间，也就是k的值减去刚刚的那个数字的概率空间，
     * 在本例当中就是减去100，也就是说第二个数是在1，900这个范围内筛选的。
     * 这样 筛选到最终，总会有一个数满足要求。
     * 就相当于去一个箱子里摸东西，
     * 第一个不是，第二个不是，第三个还不是，那最后一个一定是。
     * 这个算法简单，而且效率非常 高，
     */
    public static function getRand($proArr) {
        $result = '';  
        //概率数组的总概率精度 
        $proSum = array_sum($proArr);  
        //概率数组循环 
        foreach ($proArr as $key => $proCur) { 
            $randNum = mt_rand(1, $proSum); 
            if ($randNum <= $proCur) { 
                $result = $key; 
                break; 
            } else { 
                $proSum -= $proCur; 
            }       
        } 
        unset ($proArr);  
        return $result; 
    }


    /**
     * 精准的概率算法
     * @param $proArr //概率数组 key为参与的id  value为对应的概率
     * @return int|string
     */

    public static function getProbRand($proArr){
        $result = '';
        //概率数组的总概率精度
        $proSum = array_sum($proArr);
        $randNum = mt_rand(1, $proSum);
        $min = 0;
        foreach ($proArr as $key => $proCur) {
            if ($min < $randNum && $randNum <= $proCur + $min) {
                $result = $key;
                break;
            } else {
                $min += $proCur;
            }
        }
        unset ($proArr);
        return $result;
    }

    /**
     * 项目根目录生成打印调试日志
     * @Author czm
     * @DateTime 2020-04-15
     * @param [type] ...$params
     * @return void
     */
    public static function dd(...$params){
            ob_start();
            var_dump(...$params);
            $content=ob_get_clean();
            $file=fopen(BASE_PATH.'/dd.log','w');
            fwrite($file,$content);
            fclose($file);
    }

    /**
     * @param integer $code  返回nats的code码
     * @param string $msg   返回给nats的提示语
     * @param [type] $data  返回给nats的数据
     * @return array
     * @Description  返回nats的数据格式
     * @author wuxian
     * @since 2020-04-16
     */
    public static function nats(int $code = 0, string $msg = '', $data = []): array
    {
        return ['msg' => $msg, 'errCode' => $code, 'data' => $data];;
    }
     /**
     * 按照指定数量分块数组
     * czm
     * @param array $data
     * @param int $num
     * @return array
     */
    public static function arraySplit($data, $num = 5 )
    {
        
        $arrRet = array();
        if( !isset( $data ) || empty( $data ) )
        {
            return $arrRet;
        }
        
        $iCount = count( $data )/$num;
        if( !is_int( $iCount ) )
        {
            $iCount = ceil( $iCount );
        }
        else
        {
            $iCount += 1;
        }
        for( $i=0; $i<$iCount;++$i )
        {
            $arrInfos = array_slice($data,$i*$num, $num );
            if( empty( $arrInfos ) )
            {
                continue;
            }
            $arrRet[] = $arrInfos;
            unset( $arrInfos );
        }
        
        return $arrRet;
        
    }

    //传入整型生成一个随机码
    public static function  cipher($num){
        $table =[
            0 => 's',
            1 => 'g',
            2 => 'f',
            3 => 'm',
            4 => 'w',
            5 => '7',
            6 => 'x',
            7 => '1',
            8 => 'o',
            9 => '0',
            10 => '6',
            11 => 'u',
            12 => '5',
            13 => 'a',
            14 => 'e',
            15 => 'b',
            16 => 'd',
            17 => 'z',
            18 => '9',
            19 => 'v',
            20 => '3',
            21 => '8',
            22 => '4',
            23 => 'n',
            24 => 'k',
            25 => '2',
            25 => 'j',
            26 => 'l',
            27 => 'i',
            28 => 'r',
            29 => 'p',
            30 => 'y',
            31 => 'c',
            32 => 't',
            33 => '2',
            34 => 'q',
            35 => 'h',
        ];
        $res = '';
        $b = floatval(10000000000 + $num);
        while($b > 25){
            $res = $table[$b % 26].$res;
            $b = floor($b / 26);
        }
        $res = $table[$b].$res;
    
        return $res;
    }

    //获取redis锁
    public static function getLock($key, $expires = 10)
    {
        $now = time();
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);
        $expires = $now + $expires;
        $lock = $redis->setnx('lock_'.$key, $expires);
        if($lock){
            return true;
        }else{
            $val = $redis->get('lock_'.$key);
            if($now > $val){
                $redis->set('lock_'.$key, $expires);
                return true;
            }else{
                return false;
            }
        }
    }

    //删除redis锁
    public static function delLock($key)
    {
        $now = time();
        $container = ApplicationContext::getContainer();
        $redis = $container->get(Redis::class);

        $redis->del('lock_'.$key);
       
        
    }

    /**
     * 记录日志
     * @param $message  //日志描述
     * @param string $context  //日志的内容
     * @param string $context  //日志channel
     */
    public static function info($desc = '', $context = [], $name = 'log')
    {
        if(Context::has('co_trace_id')){
            $context['trace_id'] = Context::get('co_trace_id', '');
        }else{
            $context['trace_id'] = self::orderNo();
            Context::set('co_trace_id', $context['trace_id']);
        }
        $log = ApplicationContext::getContainer()->get(\Hyperf\Logger\LoggerFactory::class)->get($name);
        $log->info($desc, $context);
    }

    public static function log($level, $desc = '', $context = [], $name = 'log')
    {
        $log = ApplicationContext::getContainer()->get(\Hyperf\Logger\LoggerFactory::class)->get($name);
        $log->log($level, $desc, $context);
    }

    /**
     * rpc 客户端请求类
     * @Author czm
     * @DateTime 2020-05-23
     * @param string $host 服务的地址
     * @param string $route 服务路由
     * @param [array|string] $param 
     * @return void
     */
    public static function grpcClient(string $host,string $route,$param){
        if(is_array($param)){
            $param=json_encode($param);
        }
        if(!is_string($param)){
            throw new \Exception('参数错误');
        }

        $client = new \App\Grpc\HfClient($host, [
            'credentials' => null,
        ]);
        $request = new \Grpc\GrpcRequest();
        $request->setRequest($param);
        list($reply, $status) = $client->index($request,$route);
        // var_dump($reply,$status);
        $message = $reply->getReply();
        $client->close();
        return $message;
    }


    /**
     * 格式化日期
     * @param $unixTime
     * @return false|string
     */
    public static function formatDate($unixTime)
    {
        if($unixTime >= strtotime(date('Y-m-d'))){
            $date = date('H:i', $unixTime);
        } else{
            $date =  date('m/d H:i', $unixTime);
        }

        return $date;

    }
}